<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

<script src="../jquery-1.10.2.js"></script>
<script src="../jquery.tmpl.js"></script>
<script src='../knockout-2.3.0.js'></script>

</head>
<body>
<div class="loadingIndicator">
    Loading...</div>
<div class="configuration">
    <div class="listChooser">
        <button data-bind='click: deleteList, enable: editingList.name'>
            Delete</button>
        <button data-bind='click: saveChanges, enable: hasUnsavedChanges'>
            Save</button>
        <select data-bind='options: savedLists, optionsValue: "name", value: editingList.name'>
        </select>
    </div>
    <p>
        Currently viewing <span data-bind="text: editingList.userNames().length">&nbsp;</span>
        user(s):</p>
    <div class="currentUsers" data-bind='template: { name: "usersTemplate", data: editingList }'>
    </div>
    <form data-bind="submit: addUser">
    <label>
        Add user:</label>
    <input data-bind='value: userNameToAdd, valueUpdate: "keyup", css: { invalid: !userNameToAddIsValid() }' />
    <button type="submit" data-bind='enable: userNameToAddIsValid() && userNameToAdd() != ""'>
        Add</button>
    </form>
</div>

<script type="text/html" id="usersTemplate">
    <ul>
        {{each(i, userName) userNames()}}
            <li><button data-bind="click: function() { userNames.remove(userName) }">Remove</button> <div>${ userName }</div></li>
        {{/each}}
</ul>
</script>
		
	<script>
// The view model holds all the state we're working with. It also has methods that can edit it, and it uses
// dependentObservables to compute more state in terms of the underlying data
// --
// The view (i.e., the HTML UI) binds to this using data-bind attributes, so it always stays up-to-date with
// the view model, even though the view model does not know or care about any view that binds to it

var viewModel = {
    savedLists: ko.observableArray([
        { name: "Celebrities", userNames: ['JohnCleese', 'MCHammer', 'StephenFry', 'algore', 'StevenSanderson'] },
        { name: "Microsoft people", userNames: ['BillGates', 'shanselman', 'haacked', 'ScottGu'] },
        { name: "Tech pundits", userNames: ['Scobleizer', 'LeoLaporte', 'techcrunch', 'BoingBoing', 'timoreilly', 'codinghorror'] }
    ]),

    editingList: {
        name: ko.observable("Tech pundits"),
        userNames: ko.observableArray()
    },

    userNameToAdd: ko.observable(""),
    currentTweets: ko.observableArray([])
};

viewModel.findSavedList = function (name) {
    var lists = this.savedLists();

    for (var i = 0; i < lists.length; i++)
        if (lists[i].name === name)
            return lists[i];
};

// Methods
viewModel.addUser = function () {
    if (this.userNameToAdd() && this.userNameToAddIsValid()) {
        this.editingList.userNames.push(this.userNameToAdd());
        this.userNameToAdd("");
    }
}

viewModel.saveChanges = function () {
    var saveAs = prompt("Save as", this.editingList.name());

    if (saveAs) {
        var dataToSave = this.editingList.userNames().slice(0);
        var existingSavedList = this.findSavedList(saveAs);
        if (existingSavedList)
            existingSavedList.userNames = dataToSave; // Overwrite existing list
        else
            this.savedLists.push({ name: saveAs, userNames: dataToSave }); // Add new list

        this.editingList.name(saveAs);
    }
}

viewModel.deleteList = function () {
    var nameToDelete = this.editingList.name();
    var savedListsExceptOneToDelete = $.grep(this.savedLists(), function (list) { return list.name != nameToDelete });
    this.editingList.name(savedListsExceptOneToDelete.length == 0 ? null : savedListsExceptOneToDelete[0].name);
    this.savedLists(savedListsExceptOneToDelete);
};

ko.dependentObservable(function () {
    // Observe viewModel.editingList.name(), so when it changes (i.e., user selects a different list) we know to copy the saved list into the editing list
    var savedList = viewModel.findSavedList(viewModel.editingList.name());

    if (savedList) {
        var userNamesCopy = savedList.userNames.slice(0);
        viewModel.editingList.userNames(userNamesCopy);
    } else
        viewModel.editingList.userNames([]);
});

viewModel.hasUnsavedChanges = ko.dependentObservable(function () {
    if (!this.editingList.name())
        return this.editingList.userNames().length > 0;

    var savedData = this.findSavedList(this.editingList.name()).userNames;
    var editingData = this.editingList.userNames();
    return savedData.join("|") != editingData.join("|");
}, viewModel);

viewModel.userNameToAddIsValid = ko.dependentObservable(function () {
    return (this.userNameToAdd() == "") || (this.userNameToAdd().match(/^\s*[a-zA-Z0-9_]{1,15}\s*$/) != null);
}, viewModel);

ko.applyBindings(viewModel);

// Using jQuery for Ajax loading indicator - nothing to do with Knockout
$(".loadingIndicator").ajaxStart(function () { $(this).fadeIn(); })
                      .ajaxComplete(function () { $(this).fadeOut(); });
	</script>
</body>
</html>